/*
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.zhpan.bannerview;

import ohos.agp.components.AttrHelper;
import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.components.ComponentContainer;
import ohos.agp.components.DirectionalLayout;
import ohos.agp.components.Image;
import ohos.agp.components.LayoutScatter;
import ohos.agp.components.PageSlider;
import ohos.agp.components.PageSliderProvider;
import ohos.agp.components.StackLayout;
import ohos.agp.components.Text;
import ohos.agp.components.element.ElementScatter;
import ohos.agp.utils.Color;
import ohos.agp.utils.LayoutAlignment;
import ohos.agp.window.service.DisplayManager;
import ohos.app.Context;
import ohos.eventhandler.EventRunner;
import ohos.global.resource.NotExistException;
import ohos.global.resource.Resource;
import ohos.global.resource.ResourceManager;
import ohos.global.resource.WrongTypeException;
import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;
import ohos.media.image.ImageSource;
import ohos.media.image.PixelMap;
import ohos.multimodalinput.event.TouchEvent;

import com.youth.banner.ResourceTable;
import com.zhpan.bannerview.listener.OnBannerClickListener;
import com.zhpan.bannerview.listener.OnBannerListener;
import com.zhpan.bannerview.loader.ImageLoaderInterface;
import com.zhpan.bannerview.options.Options;
import com.zhpan.bannerview.view.BannerViewPagerHorizontal;

import java.io.IOException;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

import static ohos.agp.components.ComponentContainer.LayoutConfig.MATCH_PARENT;
import static ohos.multimodalinput.event.TouchEvent.CANCEL;
import static ohos.multimodalinput.event.TouchEvent.NONE;
import static ohos.multimodalinput.event.TouchEvent.PRIMARY_POINT_DOWN;
import static ohos.multimodalinput.event.TouchEvent.PRIMARY_POINT_UP;

/**
 * BannerHorizontal
 *
 * @since 2021-03-24
 */
public class BannerHorizontal extends StackLayout implements PageSlider.PageChangedListener {
    private static final int ONE = -1;
    private static final int THREE = 3;
    private static final int FIVETY = 50;
    private static final int SIXTEEN = 16;
    private static final float ONEFOUR = 1.4f;
    private static final int NINE = 9;
    private static final float ZEROFIVE = 0.5F;
    private static final int TWO = 2;
    private static final int FOUR = 4;
    private static final int FIVE = 5;
    private static final int SIX = 6;
    private static final int SEVEN = 7;
    private static final int EIGHT = 8;
    private static final int TEN = 10;
    private static final int THREEZERO = 30;
    private static final int EIGHTONE = 81;
    private static final int TWOTY = 20;
    private static final int ONEZEROZERO = 100;
    private static final int EIGHTZEROZERO = 800;
    EventRunner runner = EventRunner.current();
    private String tag = "BannerHorizontal";
    private int mIndicatorMargin = BannerConfig.PADDING_SIZE;
    private int mIndicatorWidth;
    private int mIndicatorHeight;
    private int mIndicatorSelectedWidth;
    private int mIndicatorSelectedHeight;
    private int indicatorSize;
    private int bannerBackgroundImage;
    private int bannerStyle = BannerConfig.CIRCLE_INDICATOR_TITLE_INSIDE;
    private int delayTime = BannerConfig.TIME;
    private int scrollTime = BannerConfig.DURATION;
    private boolean isAutoPlay = BannerConfig.IS_AUTO_PLAY;
    private boolean isScroll = BannerConfig.IS_SCROLL;
    private int mIndicatorSelectedResId = ResourceTable.Graphic_gray_radius;
    private int mIndicatorUnselectedResId = ResourceTable.Graphic_white_radius;
    private int mLayoutResId = ResourceTable.Layout_bannerhorizontal;
    private HiLogLabel logLabel = new HiLogLabel(HiLog.LOG_APP, 0, tag);
    private int titleHeight;
    private int titleBackground;
    private int titleTextColor;
    private int titleTextSize;
    private int startIndex;
    private int count = 0;
    private int currentItem;
    private int gravity = ONE;
    private int lastPosition = 1;
    private int scaleType = THREE;
    private List<String> titles;
    private List imageUrls;
    private List<Component> imageViews;
    private List<Component> indicatorImages;
    private Context context;
    private BannerViewPagerHorizontal viewPager;
    private Text bannerTitle;
    private Text numIndicatorInside;
    private Text numIndicator;
    private Image bannerDefaultImage;
    private ImageLoaderInterface imageLoader;
    private BannerHorizontal.BannerPagerAdapter adapter;
    private PageSlider.PageChangedListener mOnPageChangeListener;
    private BannerScroller mScroller;
    private OnBannerClickListener bannerListener;
    private OnBannerListener listener;
    private DisplayManager dm;
    private WeakHandler handler = new WeakHandler(runner);
    private IndicatorComponent indicator1; // 指示器属性
    private int orientation = Options.Orientation.INDICATOR_HORIZONTAL;
    private float normalWidthS; // 缩放
    private float checkedWidthS; // 缩放
    private float normalWidth;
    private float checkedWidth;
    private int tagPage = 0;

    /**
     * task
     */
    private final Runnable task = new Runnable() {
        @Override
        public void run() {
            int cut = tagPage + 1; // 下一个轮播页面
            if (cut >= count) {
                cut = 0; // 如果超过长度,则回到起始点
            }
            viewPager.setCurrentPage(cut);
            handler.postDelayed(task, delayTime);
        }
    };

    /**
     * Banner
     *
     * @param context 參數
     * @throws NotExistException
     * @throws WrongTypeException
     * @throws IOException
     */
    public BannerHorizontal(Context context) throws NotExistException, WrongTypeException, IOException {
        this(context, null);
    }

    /**
     * Banner
     *
     * @param context 參數
     * @param attrs 參數
     * @throws NotExistException
     * @throws WrongTypeException
     * @throws IOException
     */
    public BannerHorizontal(Context context, AttrSet attrs) throws NotExistException, WrongTypeException, IOException {
        this(context, attrs, null);
    }

    /**
     * Banner
     *
     * @param context 參數
     * @param attrs 參數
     * @param defStyle 參數
     * @throws NotExistException
     * @throws WrongTypeException
     * @throws IOException
     */
    public BannerHorizontal(Context context, AttrSet attrs, String defStyle)
        throws NotExistException, WrongTypeException, IOException {
        super(context, attrs, defStyle);
        this.context = context;
        titles = new ArrayList<>();
        imageUrls = new ArrayList<>();
        imageViews = new ArrayList<>();
        indicatorImages = new ArrayList<>();
        dm = DisplayManager.getInstance();
        indicatorSize = dm.getDefaultDisplay(context).get().getAttributes().width / FIVETY;
        initView(context, attrs);
    }

    private void initView(Context context1, AttrSet attrs) throws NotExistException, WrongTypeException, IOException {
        imageViews.clear();
        handleTypedArray(context1, attrs);
        Component component = LayoutScatter.getInstance(context1).parse(mLayoutResId, this, true);
        bannerDefaultImage = (Image) component.findComponentById(ResourceTable.Id_bannerDefaultImage);
        viewPager = (BannerViewPagerHorizontal) component.findComponentById(ResourceTable.Id_bannerViewPager);
        bannerTitle = (Text) component.findComponentById(ResourceTable.Id_bannerTitle);
        numIndicator = (Text) component.findComponentById(ResourceTable.Id_numIndicator);
        numIndicatorInside = (Text) component.findComponentById(ResourceTable.Id_numIndicatorInside);
        bannerDefaultImage.setImageAndDecodeBounds(bannerBackgroundImage);
        ((ComponentContainer) viewPager.getComponentParent()).setClipEnabled(false);
        normalWidthS = AttrHelper.vp2px(SIXTEEN, getContext());
        checkedWidthS = normalWidthS * ONEFOUR;
        normalWidth = AttrHelper.vp2px(EIGHT, getContext());
        checkedWidth = AttrHelper.vp2px(EIGHT, getContext());
        indicator1 = (IndicatorComponent) findComponentById(ResourceTable.Id_ind1);
        initViewPagerScroll();
    }

    /**
     * handleTypedArray
     *
     * @param context1 參數
     * @param attrs 參數
     * @throws NotExistException
     * @throws WrongTypeException
     * @throws IOException
     */
    private void handleTypedArray(Context context1, AttrSet attrs)
        throws NotExistException, WrongTypeException, IOException {
        ResourceManager r1 = context1.getResourceManager();
        mIndicatorWidth = indicatorSize;
        mIndicatorHeight = indicatorSize;
        mIndicatorSelectedWidth = indicatorSize;
        mIndicatorSelectedHeight = indicatorSize;
        mIndicatorMargin = BannerConfig.PADDING_SIZE;
        mIndicatorSelectedResId = ResourceTable.Graphic_gray_radius;
        mIndicatorUnselectedResId = ResourceTable.Graphic_white_radius;
        delayTime = BannerConfig.TIME;
        scrollTime = BannerConfig.DURATION;
        isAutoPlay = BannerConfig.IS_AUTO_PLAY;
        titleBackground = BannerConfig.TITLE_BACKGROUND;
        titleHeight = BannerConfig.TITLE_HEIGHT;
        titleTextColor = BannerConfig.TITLE_TEXT_COLOR;
        titleTextSize = BannerConfig.TITLE_TEXT_SIZE;
        mLayoutResId = mLayoutResId;
        bannerBackgroundImage = ResourceTable.Media_no_banner;
    }

    private void initViewPagerScroll() {
        try {
            Field mField = PageSlider.class.getDeclaredField("mScroller");
            mField.setAccessible(true);
            mScroller = new BannerScroller(viewPager.getContext());
            mScroller.setDuration(scrollTime);
            mField.set(viewPager, mScroller);
        } catch (NoSuchFieldException e) {
            Log.debug(e.getMessage());
        } catch (IllegalAccessException e) {
            Log.debug(e.getMessage());
        }
    }

    /**
     * isAutoPlay
     *
     * @param isAutoPlay1 參數
     * @return this
     */
    public BannerHorizontal isAutoPlay(boolean isAutoPlay1) {
        this.isAutoPlay = isAutoPlay1;
        return this;
    }

    /**
     * setImageLoader
     *
     * @param imageLoader 參數
     * @return this
     */
    public BannerHorizontal setImageLoader(ImageLoaderInterface imageLoader) {
        this.imageLoader = imageLoader;
        return this;
    }

    /**
     * setBannerBackgroundImage
     *
     * @param attr 參數
     * @return this
     */
    public BannerHorizontal setBannerBackgroundImage(int attr) {
        this.bannerBackgroundImage = attr;
        return this;
    }

    /**
     * setDelayTime
     *
     * @param delayTime 參數
     * @return this
     */
    public BannerHorizontal setDelayTime(int delayTime) {
        this.delayTime = delayTime;
        return this;
    }

    /**
     * setTitleHeight
     *
     * @param attr 參數
     * @return this
     */
    public BannerHorizontal setTitleHeight(int attr) {
        this.titleHeight = attr;
        return this;
    }

    /**
     * setTitleTextColor
     *
     * @param attr 參數
     * @return this
     */
    public BannerHorizontal setTitleTextColor(int attr) {
        this.titleTextColor = attr;
        return this;
    }

    /**
     * setTitleTextSize
     *
     * @param attr1 參數
     * @return this
     */
    public BannerHorizontal setTitleTextSize(int attr1) {
        this.titleTextSize = attr1;

        return this;
    }

    /**
     * setTitleBackground
     *
     * @param attr1 參數
     * @return this
     */
    public BannerHorizontal setTitleBackground(int attr1) {
        this.titleBackground = attr1;
        return this;
    }

    /**
     * setMindicatorWidth
     *
     * @param attr1 參數
     * @return this
     */
    public BannerHorizontal setMindicatorWidth(int attr1) {
        this.mIndicatorWidth = attr1;
        return this;
    }

    /**
     * setMindicatorHeight
     *
     * @param attr1 參數
     * @return this
     */
    public BannerHorizontal setMindicatorHeight(int attr1) {
        this.mIndicatorHeight = attr1;
        return this;
    }

    /**
     * setMIndicatorSelectedWidth
     *
     * @param attr1 參數
     * @return this
     */
    public BannerHorizontal setMindicatorSelectedWidth(int attr1) {
        this.mIndicatorSelectedWidth = attr1;
        return this;
    }

    /**
     * setMindicatorSelectedHeight
     *
     * @param attr1 參數
     * @return this
     */
    public BannerHorizontal setMindicatorSelectedHeight(int attr1) {
        this.mIndicatorSelectedHeight = attr1;
        return this;
    }

    /**
     * setMindicatorSelectedResId
     *
     * @param attr1 參數
     * @return this
     */
    public BannerHorizontal setMindicatorSelectedResId(int attr1) {
        this.mIndicatorSelectedResId = attr1;
        return this;
    }

    /**
     * setMIndicatorUnselectedResId
     *
     * @param attr1 參數
     * @return this
     */
    public BannerHorizontal setMindicatorUnselectedResId(int attr1) {
        this.mIndicatorUnselectedResId = attr1;
        return this;
    }

    /**
     * setMIndicatorMargin
     *
     * @param attr1 參數
     * @return this
     */
    public BannerHorizontal setMindicatorMargin(int attr1) {
        this.mIndicatorMargin = attr1;
        return this;
    }

    /**
     * setScaleType
     *
     * @param scale 參數
     * @return this
     */
    public BannerHorizontal setScaleType(int scale) {
        scaleType = scale;
        return this;
    }

    private void setScaleType(Component imageView) {
        if (imageView instanceof Image) {
            Image view = (Image) imageView;
            switch (scaleType) {
                case 0:
                    view.setScaleMode(Image.ScaleMode.CENTER);
                    break;
                case 1:
                    view.setScaleMode(Image.ScaleMode.CLIP_CENTER);
                    break;
                case TWO:
                    view.setScaleMode(Image.ScaleMode.INSIDE);
                    break;
                case THREE:
                    view.setScaleMode(Image.ScaleMode.ZOOM_CENTER);
                    break;
                case FOUR:
                    view.setScaleMode(Image.ScaleMode.ZOOM_END);
                    break;
                case FIVE:
                    view.setScaleMode(Image.ScaleMode.ZOOM_START);
                    break;
                case SIX:
                    view.setScaleMode(Image.ScaleMode.ZOOM_CENTER);
                    break;
                case SEVEN:
                    view.setScaleMode(Image.ScaleMode.STRETCH);
                    break;
                default:
                    break;
            }
        }
    }

    /**
     * setIndicatorGravity
     *
     * @param type 參數
     * @return this
     */
    public BannerHorizontal setIndicatorGravity(int type) {
        switch (type) {
            case BannerConfig.LEFT:
                this.gravity = LayoutAlignment.LEFT | LayoutAlignment.VERTICAL_CENTER;
                break;
            case BannerConfig.CENTER:
                this.gravity = LayoutAlignment.CENTER;
                break;
            case BannerConfig.RIGHT:
                this.gravity = LayoutAlignment.RIGHT | LayoutAlignment.VERTICAL_CENTER;
                break;
            default:
                break;
        }
        return this;
    }

    /**
     * setBannerTitles
     *
     * @param titles1 參數
     * @return this
     */
    public BannerHorizontal setBannerTitles(List<String> titles1) {
        this.titles = titles1;
        return this;
    }

    /**
     * setBannerStyle
     *
     * @param bannerStyle 參數
     * @return this
     */
    public BannerHorizontal setBannerStyle(int bannerStyle) {
        this.bannerStyle = bannerStyle;
        return this;
    }

    /**
     * setViewPagerIsScroll
     *
     * @param isScroll1 參數
     * @return this
     */
    public BannerHorizontal setViewPagerIsScroll(boolean isScroll1) {
        this.isScroll = isScroll1;
        return this;
    }

    /**
     * setImages
     *
     * @param imageUrls1 參數
     * @return this
     */
    public BannerHorizontal setImages(List<?> imageUrls1) {
        this.imageUrls.addAll(imageUrls1);
        this.count = imageUrls.size();
        return this;
    }

    /**
     * update
     *
     * @param imageUrls1 參數
     * @param titles1 參數
     * @throws NotExistException
     * @throws WrongTypeException
     * @throws IOException
     */
    public void update(List<?> imageUrls1, List<String> titles1)
        throws NotExistException, WrongTypeException, IOException {
        this.titles.clear();
        this.titles.addAll(titles1);
        update(imageUrls1);
    }

    /**
     * update
     *
     * @param imageUrls1 參數
     * @throws NotExistException
     * @throws WrongTypeException
     * @throws IOException
     */
    public void update(List<?> imageUrls1) throws NotExistException, WrongTypeException, IOException {
        this.imageUrls.clear();
        this.imageViews.clear();
        this.indicatorImages.clear();
        this.imageUrls.addAll(imageUrls1);
        this.count = this.imageUrls.size();
        start();
    }

    /**
     * updateBannerStyle
     *
     * @param bannerStyle1 參數
     * @throws NotExistException
     * @throws WrongTypeException
     * @throws IOException
     */
    public void updateBannerStyle(int bannerStyle1) throws NotExistException, WrongTypeException, IOException {
        numIndicator.setVisibility(HIDE);
        numIndicatorInside.setVisibility(HIDE);
        bannerTitle.setVisibility(HIDE);
        this.bannerStyle = bannerStyle1;
        start();
    }

    /**
     * updateOne
     *
     * @throws NotExistException
     * @throws WrongTypeException
     * @throws IOException
     */
    public void setBannerNumStyle() throws NotExistException, WrongTypeException, IOException {
        numIndicator.setVisibility(HIDE);
        this.bannerStyle = bannerStyle;
        start();
    }

    /**
     * start
     *
     * @return this
     * @throws NotExistException
     * @throws WrongTypeException
     * @throws IOException
     */
    public BannerHorizontal start() throws NotExistException, WrongTypeException, IOException {
        setBannerStyleUi();
        setImageList(imageUrls);
        setData();
        return this;
    }

    /**
     * start1
     *
     * @return this
     * @throws NotExistException
     * @throws WrongTypeException
     * @throws IOException
     */
    public BannerHorizontal start1() throws NotExistException, WrongTypeException, IOException {
        setBannerNumStyle();
        setBannerStyleUi();
        setImageList(this.imageUrls);
        setData();
        setIndicatorInsideRound();
        numIndicator.setVisibility(HIDE);
        numIndicatorInside.setVisibility(HIDE);
        bannerTitle.setVisibility(HIDE);
        return this;
    }

    /**
     * setTitleStyleUI
     */
    private void setTitleStyleUi() {
        if (titleBackground != ONE) {
            Log.debug("22222");
        }
        if (titleHeight != ONE) {
            Log.debug("33333");
        }
        if (titleTextColor != ONE) {
            bannerTitle.setTextColor(new Color(titleTextColor));
        }
        if (titleTextSize != ONE) {
            bannerTitle.setTextSize(titleTextSize);
        }
        if (titles != null && titles.size() > 0) {
            bannerTitle.setText(titles.get(0));
            bannerTitle.setVisibility(HIDE);
        }
    }

    private void setBannerStyleUi() {
        int visibility = count > 1 ? VISIBLE : HIDE;
        switch (bannerStyle) {
            case BannerConfig.CIRCLE_INDICATOR:
                break;
            case BannerConfig.NUM_INDICATOR:
                numIndicator.setVisibility(visibility);
                break;
            case BannerConfig.NUM_INDICATOR_TITLE:
                numIndicatorInside.setVisibility(visibility);
                setTitleStyleUi();
                break;
            case BannerConfig.CIRCLE_INDICATOR_TITLE:
                setTitleStyleUi();
                break;
            case BannerConfig.CIRCLE_INDICATOR_TITLE_INSIDE:
                break;
            default:
                break;
        }
    }

    private void initImages() {
        imageViews.clear();
        if (bannerStyle == BannerConfig.CIRCLE_INDICATOR
            || bannerStyle == BannerConfig.CIRCLE_INDICATOR_TITLE
            || bannerStyle == BannerConfig.CIRCLE_INDICATOR_TITLE_INSIDE) {
            createIndicator();
        } else if (bannerStyle == BannerConfig.NUM_INDICATOR_TITLE) {
            numIndicatorInside.setText("1/" + count);
        } else if (bannerStyle == BannerConfig.NUM_INDICATOR) {
            numIndicator.setText("1/" + count);
        }
    }

    private void setImageList(List<?> imagesUrl) throws NotExistException, WrongTypeException, IOException {
        if (imagesUrl == null || imagesUrl.size() <= 0) {
            bannerDefaultImage.setVisibility(VISIBLE);
            return;
        }
        bannerDefaultImage.setVisibility(HIDE);
        initImages();
        for (int i1 = 0; i1 < count; i1++) {
            Object url = null;
            if (i1 == 0) {
                url = imagesUrl.get(count - 1);
            } else if (i1 == count + 1) {
                url = imagesUrl.get(0);
            } else {
                url = imagesUrl.get(i1 - 1);
            }
            Image image1 = new Image(context);
            setScaleType(image1);
            ImageSource.SourceOptions options = new ImageSource.SourceOptions();
            options.formatHint = "image/jpg";
            ImageSource.DecodingOptions decodingOptions = new ImageSource.DecodingOptions();
            ResourceManager manager = context.getResourceManager();
            String path = manager.getMediaPath((Integer) url);
            Resource r1 = manager.getRawFileEntry(path).openRawFile();
            ImageSource source = ImageSource.create(r1, options);
            PixelMap p1 = source.createPixelmap(decodingOptions);
            image1.setPixelMap(p1);
            image1.setLayoutConfig(new DirectionalLayout.LayoutConfig(
                MATCH_PARENT, MATCH_PARENT, LayoutAlignment.CENTER, ZEROFIVE));
            imageViews.add(image1);
        }
    }

    /**
     * createIndicator
     */
    private void createIndicator() {
        indicatorImages.clear();
        for (int i1 = 0; i1 < count; i1++) {
            Component component1 = new Component(context);

            DirectionalLayout.LayoutConfig params;
            if (i1 == 0) {
                params = new DirectionalLayout.LayoutConfig(mIndicatorSelectedWidth, mIndicatorSelectedHeight);
                HiLog.fatal(logLabel, String.valueOf(mIndicatorSelectedWidth));
                HiLog.fatal(logLabel, String.valueOf(mIndicatorSelectedHeight));
                component1.setBackground(ElementScatter.getInstance(getContext()).parse(mIndicatorSelectedResId));
            } else {
                params = new DirectionalLayout.LayoutConfig(mIndicatorWidth, mIndicatorHeight);
                component1.setBackground(ElementScatter.getInstance(getContext()).parse(mIndicatorUnselectedResId));
                HiLog.fatal(logLabel, String.valueOf(mIndicatorWidth));
                HiLog.fatal(logLabel, String.valueOf(mIndicatorHeight));
            }
            params.setMargins(mIndicatorMargin, TEN, mIndicatorMargin, TEN);
            indicatorImages.add(component1);
            if (bannerStyle == BannerConfig.CIRCLE_INDICATOR
                || bannerStyle == BannerConfig.CIRCLE_INDICATOR_TITLE) {
                Log.debug("11111");
            }
            else if (bannerStyle == BannerConfig.CIRCLE_INDICATOR_TITLE_INSIDE) {
                Log.debug("11111");
            }
        }
    }

    private void setData() {
        if (startIndex != 0) {
            currentItem = startIndex;
        } else {
            currentItem = 1;
        }
        if (adapter == null) {
            adapter = new BannerHorizontal.BannerPagerAdapter();
            viewPager.addPageChangedListener(this);
            viewPager.setProvider(adapter);
        } else {
            adapter.notifyDataChanged();
        }
        viewPager.setFocusable(1);
        if (gravity != ONE) {
            if (isScroll && count > 1) {
                viewPager.setScrollable(true);
            } else {
                viewPager.setScrollable(false);
            }
        }
        if (isAutoPlay) {
            startAutoPlay();
        }
        this.setTouchEventListener(new TouchEventListener() {
            @Override
            public boolean onTouchEvent(Component component, TouchEvent touchEvent) {
                if (isAutoPlay) {
                    int action = touchEvent.getAction();
                    if (action == PRIMARY_POINT_UP || action == CANCEL
                        || action == NONE) {
                        startAutoPlay();
                    } else if (action == PRIMARY_POINT_DOWN) {
                        stopAutoPlay();
                    }
                }
                return true;
            }
        });
    }

    /**
     * startAutoPlay
     */
    public void startAutoPlay() {
        handler.removeCallbacks(task);
        handler.postDelayed(task, delayTime);
    }

    /**
     * stopAutoPlay
     */
    public void stopAutoPlay() {
        handler.removeCallbacks(task);
    }

    /**
     * 返回真实的位置
     *
     * @param position 參數
     * @return 下标从0开始
     */
    public int toRealPosition(int position) {
        int realPosition = 0;
        if (count != 0) {
            realPosition = (position - 1) % count;
        }
        if (realPosition < 0) {
            realPosition += count;
        }
        return realPosition;
    }

    @Override
    public void onPageSliding(int position, float positionOffset, int positionOffsetPixels) {
        if (mOnPageChangeListener != null) {
            mOnPageChangeListener.onPageSliding(toRealPosition(position), positionOffset, positionOffsetPixels);
        }
    }

    @Override
    public void onPageSlideStateChanged(int state) {
        if (mOnPageChangeListener != null) {
            mOnPageChangeListener.onPageSlideStateChanged(state);
        }
        switch (state) {
            case 0: // No operation
                if (currentItem == 0) {
                    viewPager.setCurrentPage(count, false);
                } else if (currentItem == count + 1) {
                    viewPager.setCurrentPage(1, false);
                }
                break;
            case 1: // start Sliding
                if (currentItem == count + 1) {
                    viewPager.setCurrentPage(1, false);
                } else if (currentItem == 0) {
                    viewPager.setCurrentPage(count, false);
                }
                break;
            case TWO: // end Sliding
                break;
            default:
                break;
        }
    }

    @Override
    public void onPageChosen(int position) {
        currentItem = position;tagPage = position;
        if (mOnPageChangeListener != null) {
            mOnPageChangeListener.onPageChosen(toRealPosition(position));
        }
        if (bannerStyle == BannerConfig.CIRCLE_INDICATOR
            || bannerStyle == BannerConfig.CIRCLE_INDICATOR_TITLE
            || bannerStyle == BannerConfig.CIRCLE_INDICATOR_TITLE_INSIDE) {
            DirectionalLayout.LayoutConfig
                selectedparams = new DirectionalLayout
                .LayoutConfig(mIndicatorSelectedWidth, mIndicatorSelectedHeight);
            selectedparams.setMargins(mIndicatorMargin, TEN, mIndicatorMargin, TEN);
            DirectionalLayout.LayoutConfig
                unselectedparams = new DirectionalLayout.LayoutConfig(mIndicatorWidth, mIndicatorHeight);
            unselectedparams.setMargins(mIndicatorMargin, TEN, mIndicatorMargin, TEN);
            indicatorImages.get((lastPosition - 1 + count) % count)
                .setBackground(ElementScatter.getInstance(getContext()).parse(mIndicatorUnselectedResId));
            indicatorImages.get((lastPosition - 1 + count) % count).setLayoutConfig(unselectedparams);
            indicatorImages.get((position - 1 + count) % count)
                .setBackground(ElementScatter.getInstance(getContext()).parse(mIndicatorSelectedResId));
            indicatorImages.get((position - 1 + count) % count).setLayoutConfig(selectedparams);
            lastPosition = position;
        }
        int posi = position;
        if (position == 0) {
            posi = count;
        }
        if (position > count) {
            posi = 1;
        }
        switch (bannerStyle) {
            case BannerConfig.CIRCLE_INDICATOR:
                break;
            case BannerConfig.NUM_INDICATOR:
                numIndicator.setText(posi + "/" + count);
                break;
            case BannerConfig.NUM_INDICATOR_TITLE:
                numIndicatorInside.setText(posi + "/" + count);
                bannerTitle.setText(titles.get(posi - 1));
                break;
            case BannerConfig.CIRCLE_INDICATOR_TITLE:
                bannerTitle.setText(titles.get(posi - 1));
                break;
            case BannerConfig.CIRCLE_INDICATOR_TITLE_INSIDE:
                bannerTitle.setText(titles.get(posi - 1));
                break;
            default:
                break;
        }
    }
    /**
     * BannerPagerAdapter
     *
     * @since 2021-03-24
     */
    class BannerPagerAdapter extends PageSliderProvider {
        @Override
        public int getCount() {
            return imageViews.size();
        }

        @Override
        public Object createPageInContainer(ComponentContainer container, final int position) {
            container.addComponent(imageViews.get(position));
            Component view = imageViews.get(position);
            if (bannerListener != null) {
                view.setClickedListener(v1 -> {
                    HiLogLabel logLabel1 = new HiLogLabel(HiLog.ERROR, 0, tag);
                    HiLog.error(logLabel1, "你正在使用旧版点击事件接口，下标是从1开始，"
                        + "为了体验请更换为setOnBannerListener，下标从0开始计算");
                    bannerListener.onBannerClick(position);
                });
            }
            if (listener != null) {
                view.setClickedListener(new ClickedListener() {
                    @Override
                    public void onClick(Component v1) {
                        listener.onBannerClick(toRealPosition(position));
                    }
                });
            }
            return view;
        }

        @Override
        public void destroyPageFromContainer(ComponentContainer componentContainer, int i1, Object o1) {
            componentContainer.removeComponent((Component) o1);
        }

        @Override
        public boolean isPageMatchToObject(Component component, Object o1) {
            return component == o1;
        }
    }

    /**
     * setOnBannerClickListener
     *
     * @param listener1 參數
     * @return this
     */
    @Deprecated
    public BannerHorizontal setOnBannerClickListener(OnBannerClickListener listener1) {
        this.bannerListener = listener1;
        return this;
    }

    /**
     * 废弃了旧版接口，新版的接口下标是从1开始，同时解决下标越界问题
     *
     * @param listener1 參數
     * @return this
     */
    public BannerHorizontal setOnBannerListener(OnBannerListener listener1) {
        this.listener = listener1;
        return this;
    }

    /**
     * setStartIndex
     *
     * @param index 參數
     * @return this
     */
    public BannerHorizontal setStartIndex(int index) {
        this.startIndex = index;
        return this;
    }

    /**
     * setOnPageChangeListener
     *
     * @param onPageChangeListener 參數
     */
    public void setOnPageChangeListener(PageSlider.PageChangedListener onPageChangeListener) {
        mOnPageChangeListener = onPageChangeListener;
    }

    /**
     * releaseBanner
     */
    public void releaseBanner() {
        handler.removeCallbacksAndMessages(null);
    }

    /**
     * 指示器的基本配置
     */
    public void setIndicatorInside() {
        // 基本指示器配置
        indicator1.setVisibility(Component.VISIBLE);
        indicator1.setSlideMode(Options.IndicatorMode.WORM);
        indicator1.setIndicatorStyle(Options.IndicatorStyle.CIRCLE);
        indicator1.setSliderHeight(AttrHelper.vp2px(SIX, getContext()));
        indicator1.setSliderGap(AttrHelper.vp2px(EIGHT, getContext()));
        indicator1.setOrientation(Options.Orientation.INDICATOR_HORIZONTAL);
        indicator1.setSliderWidth(normalWidth, checkedWidth);
        indicator1.setupWithPageSlide(viewPager);
    }

    /**
     * 基本指示器配置
     */
    public void setIndicatorInsideRound() {
        indicator1.setSlideMode(Options.IndicatorMode.WORM);
        indicator1.setIndicatorStyle(Options.IndicatorStyle.ROUND_RECT);
        indicator1.setSliderHeight(AttrHelper.vp2px(SIX, getContext()));
        indicator1.setSliderGap(AttrHelper.vp2px(EIGHT, getContext()));
        indicator1.setOrientation(Options.Orientation.INDICATOR_VERTICAL);
        indicator1.setSliderWidth(normalWidth, checkedWidth);
        indicator1.setupWithPageSlide(viewPager);
    }
}

